import os

from pathlib import Path
import uvicorn
import platform
import signal

from fastapi import FastAPI, Body, Request
from fastapi.staticfiles import StaticFiles
from fastapi.middleware.cors import CORSMiddleware
from fastapi.middleware.gzip import GZipMiddleware
from fastapi.middleware.cors import CORSMiddleware
from starlette.middleware.sessions import SessionMiddleware
from starlette.responses import RedirectResponse, FileResponse, HTMLResponse
from fastapi import (
    FastAPI, 
    APIRouter,
    Depends,
    Body,
)

from gqWorkspace.api import FileMgrApi, FactorApi, VersionApi

class GqWorkspace():
    name = "GqWorkspace"
    description = "Analysis Workspace for GrandQuants"
    
    '''
    param {str} static_folder  静态文件根目录
    '''
    def __init__(self, static_folder: str = r"front/"):
        self.static_folder = Path(static_folder)

        self.app = FastAPI(title=self.name, description=self.description, redoc_url=None, version="1.0.0")
        
        self.init_app(self.app)
        self.init_front(self.app, static_folder)
        
        # 注册api
        self.app.include_router(FileMgrApi.router())
        self.app.include_router(FactorApi.router())
        self.app.include_router(VersionApi.router())
        
        self.worker = None
        
    def init_app(self, app: FastAPI):
        app.add_middleware(GZipMiddleware, minimum_size=1000)
        app.add_middleware(SessionMiddleware, secret_key='!@#$%^&*()', max_age=25200, session_cookie='WtMonSvr_sid')
        app.add_middleware(
            CORSMiddleware,
            allow_origins=["*"],
            allow_credentials=True,
            allow_methods=["*"],
            allow_headers=["*"])
        
        @app.middleware("http")
        async def add_process_time_header(request: Request, call_next):
            response = await call_next(request)
            if request.url.__str__().endswith('.js'):
                response.headers['Content-Type'] = 'application/javascript'
            return response
        
    def init_front(self, app: FastAPI, static_folder: str):
        script_dir = Path(__file__).parent
        static_folder = script_dir.joinpath(static_folder)
        if static_folder.exists():
            app.mount("/console", StaticFiles(directory=static_folder.as_posix()), name="front")
            app.mount("/static", StaticFiles(directory=static_folder.joinpath("static").as_posix()), name="static")

        @app.get("/")
        @app.get("/console")
        async def console_index():
            with open(static_folder.joinpath("index.html").as_posix()) as f:
                html_content = f.read()
            return HTMLResponse(content=html_content, status_code=200)
        
    def __run_impl__(self, port: int, host: str):
        # log_config = uvicorn.config.LOGGING_CONFIG
        # log_config["formatters"]["access"]["fmt"] =  "%(asctime)s - [%(filename)s:%(lineno)d-%(funcName)s] <%(levelname)s>: %(message)s"
        # log_config["formatters"]["default"]["fmt"] = "%(asctime)s - [%(filename)s:%(lineno)d-%(funcName)s] <%(levelname)s>: %(message)s"
        uvicorn.run(self.app, port=port, host=host)
        
    def run(self, port: int = 8080, host="127.0.0.1", bSync: bool = True):
        # 仅linux生效，在linux中，子进程会一直等待父进程处理其结束信号才能释放，如果不加这一句忽略子进程的结束信号，子进程就无法结束
        if "windows" not in platform.system().lower():
            signal.signal(signal.SIGCHLD, signal.SIG_IGN)
        if bSync:
            self.__run_impl__(port, host)
        else:
            import threading
            self.worker = threading.Thread(target=self.__run_impl__, args=(port, host,))
            self.worker.setDaemon(True)
            self.worker.start()